/*
 * Copyright 2008 The Brui Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
 
package com.googlecode.brui;

import static java.awt.BorderLayout.CENTER;
import static java.awt.BorderLayout.EAST;
import static java.awt.BorderLayout.SOUTH;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.util.Calendar;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreeModel;

import com.googlecode.brui.components.table.BeanPropertyTableModel;
import com.googlecode.brui.components.tree.BeanTreeModel;

/**
 * Application for testing BRUI front end.
 */
public class App {
	public static void main(final String[] args) {
		final JFrame frame = new JFrame("BRUI Test App");
		final Container contentPane = frame.getContentPane();

		final JTabbedPane tabbedPane = new JTabbedPane();
		tabbedPane.addTab("Tree/Table Models", createModelsTab());

		contentPane.add(tabbedPane);

		frame.setSize(640, 480);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	private static Component createModelsTab() {
		final TreeModel treeModel = createTreeModel();
		final JTree beanTree = new JTree(treeModel);
		final BeanPropertyTableModel tableModel = createTableModel();
		final JTable beanPropertyTable = new JTable(tableModel);
		beanTree.addTreeSelectionListener(new TreeSelectionListener() {
			@Override
			public void valueChanged(final TreeSelectionEvent e) {
				tableModel.setBean(e.getPath().getLastPathComponent());
			}
		});
		tableModel.addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(final TableModelEvent e) {
				beanTree.treeDidChange(); // FIXME correctly notify tree of change
			}
		});
		final JScrollPane treePane = new JScrollPane(beanTree);
		final JScrollPane tablePane = new JScrollPane(beanPropertyTable);
		final JPanel panel = new JPanel(new BorderLayout());
		panel.add(treePane, CENTER);
		panel.add(tablePane, EAST);
		panel.add(createModelsDescription(), SOUTH);
		return panel;
	}

	private static Component createModelsDescription() {
		final String text = "The bean tree shows all the beans in a simple Java object graph. "
				+ "The bean property table shows all the properties of the selected bean from the bean tree. "
				+ "Bean properties can be modified from the table cells.";
		final JTextArea textArea = new JTextArea(text);
		textArea.setEditable(false);
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);
		textArea.setRows(4);
		return new JScrollPane(textArea, VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_NEVER);
	}

	private static BeanPropertyTableModel createTableModel() {
		return new BeanPropertyTableModel();
	}

	private static TreeModel createTreeModel() {
		final Calendar calendar = Calendar.getInstance();

		calendar.set(1973, 7, 23);
		final Patient patient1 = new Patient("John", "Doe", calendar.getTime());
		patient1.setAddress(new Address("Home", "21 Wakefield Street", "London", "England"));

		calendar.set(1974, 3, 14);
		final Patient patient2 = new Patient("Jane", "Stag", calendar.getTime());
		patient2.setAddress(new Address("Work", "1280 Queen Street", "London", "England"));

		final ReallySmallHospital hospital = new ReallySmallHospital();
		hospital.setPatient1(patient1);
		hospital.setPatient2(patient2);

		return new BeanTreeModel(hospital);
	}

	public static class ReallySmallHospital {
		private Patient patient1;
		private Patient patient2;

		@Override
		public String toString() {
			return "Two-Bed Hospital";
		}

		public Patient getPatient1() {
			return patient1;
		}

		public void setPatient1(final Patient patient1) {
			this.patient1 = patient1;
		}

		public Patient getPatient2() {
			return patient2;
		}

		public void setPatient2(final Patient patient2) {
			this.patient2 = patient2;
		}
	}

	public static class Patient {
		private String givenName;
		private String surname;
		private Date dob;
		private Address address;

		public Patient() {

		}

		public Patient(final String givenName, final String surname, final Date dob) {
			this.givenName = givenName;
			this.surname = surname;
			this.dob = dob;
		}

		@Override
		public String toString() {
			final StringBuilder nameStringBuilder = new StringBuilder();
			if (!empty(surname)) {
				nameStringBuilder.append(surname);
				if (!empty(givenName)) {
					nameStringBuilder.append(", ");
					nameStringBuilder.append(givenName);
				}
			} else if (!empty(givenName)) {
				nameStringBuilder.append(givenName);
			} else {
				nameStringBuilder.append("UNKNOWN PATIENT");
			}
			return nameStringBuilder.toString();
		}

		private static boolean empty(final String s) {
			return s == null || "".equals(s.trim());
		}

		public String getGivenName() {
			return givenName;
		}

		public void setGivenName(final String givenName) {
			this.givenName = givenName;
		}

		public String getSurname() {
			return surname;
		}

		public void setSurname(final String surname) {
			this.surname = surname;
		}

		public Date getDob() {
			return dob;
		}

		public void setDob(final Date dob) {
			this.dob = dob;
		}

		public Address getAddress() {
			return address;
		}

		public void setAddress(final Address address) {
			this.address = address;
		}
	}

	public static class Address {
		private String type;
		private String street;
		private String city;
		private String country;

		public Address() {
		}

		public Address(final String type, final String street, final String city, final String country) {
			super();
			this.type = type;
			this.street = street;
			this.city = city;
			this.country = country;
		}

		@Override
		public String toString() {
			return "Address" + (type == null ? "" : " (" + type + ")");
		}

		public String getCity() {
			return city;
		}

		public void setCity(final String city) {
			this.city = city;
		}

		public String getCountry() {
			return country;
		}

		public void setCountry(final String country) {
			this.country = country;
		}

		public String getStreet() {
			return street;
		}

		public void setStreet(final String street) {
			this.street = street;
		}

		public String getType() {
			return type;
		}

		public void setType(final String type) {
			this.type = type;
		}
	}
}
